<article id="wikiArticle">
<div></div>
<p><code><strong>Object.defineProperty()</strong></code> 方法会直接在一个对象上定义一个新属性，或者修改一个对象的现有属性， 并返回这个对象。</p>
<h2 id="语法">语法</h2>
<pre><code class="language-javascript"><code>Object.defineProperty(<var>obj</var>, <var>prop</var>, <var>descriptor</var>)</code></code></pre>
<h3 id="Parameters" name="Parameters">参数</h3>
<dl>
<dt><code>obj</code></dt>
<dd>要在其上定义属性的对象。</dd>
<dt><code>prop</code></dt>
<dd>要定义或修改的属性的名称。</dd>
<dt><code>descriptor</code></dt>
<dd>将被定义或修改的属性描述符。</dd>
</dl>
<h3 id="返回值">返回值</h3>
<p>    被传递给函数的对象。</p>
<div class="note">
<p>在ES6中，由于 Symbol类型的特殊性，用Symbol类型的值来做对象的key与常规的定义或修改不同，而<code>Object.defineProperty</code> 是定义key为Symbol的属性的方法之一。</p>
</div>
<h2 id="Description" name="Description">描述</h2>
<p> </p>
<p>该方法允许精确添加或修改对象的属性。通过赋值操作添加的普通属性是可枚举的，能够在属性枚举期间呈现出来（<a href="Reference/Statements/for...in" title="for...in语句以任意顺序遍历一个对象的可枚举属性。对于每个不同的属性，语句都会被执行。"><code>for...in</code></a> 或 <a href="Reference/Global_Objects/Object/keys" title="Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组，数组中属性名的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致 。"><code>Object.keys</code></a><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys" title="JavaScript/Reference/Global_Objects/Object/keys"> </a>方法）， 这些属性的值可以被改变，也可以被<a href="Reference/Operators/delete" title="delete 操作符用于删除对象的某个属性；如果没有指向这个属性的引用，那它最终会被释放。">删除</a>。这个方法允许修改默认的额外选项（或配置）。默认情况下，使用 <code>Object.defineProperty()</code> 添加的属性值是不可修改的。</p>
<p> </p>
<h2 id="属性描述符">属性描述符</h2>
<p> </p>
<p>对象里目前存在的属性描述符有两种主要形式：<strong>数据描述符</strong>和<strong>存取描述符</strong>。<strong>数据描述符</strong>是一个具有值的属性，该值可能是可写的，也可能不是可写的。<strong>存取描述符</strong>是由getter-setter函数对描述的属性。描述符必须是这两种形式之一；不能同时是两者。</p>
<p><strong>数据描述符和存取描述符均具有</strong>以下可选键值：</p>
<dl>
<dt><code>configurable</code></dt>
<dd>当且仅当该属性的 configurable 为 true 时，该属性<code>描述符</code>才能够被改变，同时该属性也能从对应的对象上被删除。<strong>默认为 false</strong>。</dd>
<dt><code>enumerable</code></dt>
<dd>当且仅当该属性的<code>enumerable</code>为<code>true</code>时，该属性才能够出现在对象的枚举属性中。<strong>默认为 false</strong>。</dd>
</dl>
<p><strong>数据描述符同时具有以下可选键值</strong>：</p>
<dl>
<dt><code>value</code></dt>
<dd>该属性对应的值。可以是任何有效的 JavaScript 值（数值，对象，函数等）。<strong>默认为 <a href="Reference/Global_Objects/undefined" title="undefined是全局对象的一个属性。也就是说，它是全局作用域的一个变量。undefined的最初值就是原始数据类型undefined。"><code>undefined</code></a></strong>。</dd>
<dt><code>writable</code></dt>
<dd>当且仅当该属性的<code>writable</code>为<code>true</code>时，<code>value</code>才能被<a href="Reference/Operators/Assignment_Operators" title="赋值运算符（assignment operator）基于右值（right operand）的值，给左值（left operand）赋值。">赋值运算符</a>改变。<strong>默认为 <font face="consolas, Liberation Mono, courier, monospace">false</font></strong>。</dd>
</dl>
<p><strong>存取描述符同时具有以下可选键值</strong>：</p>
<dl>
<dt><code>get</code></dt>
<dd>一个给属性提供 getter 的方法，如果没有 getter 则为 <code>undefined</code>。当访问该属性时，该方法会被执行，方法执行时没有参数传入，但是会传入<code>this</code>对象（由于继承关系，这里的<code>this</code>并不一定是定义该属性的对象）。</dd>
<dd><strong>默认为 <a href="Reference/Global_Objects/undefined" title="undefined是全局对象的一个属性。也就是说，它是全局作用域的一个变量。undefined的最初值就是原始数据类型undefined。"><code>undefined</code></a></strong>。</dd>
<dt><code>set</code></dt>
<dd>一个给属性提供 setter 的方法，如果没有 setter 则为 <code>undefined</code>。当属性值修改时，触发执行该方法。该方法将接受唯一参数，即该属性新的参数值。</dd>
<dd><strong>默认为 <a href="Reference/Global_Objects/undefined" title="undefined是全局对象的一个属性。也就是说，它是全局作用域的一个变量。undefined的最初值就是原始数据类型undefined。"><code>undefined</code></a></strong>。</dd>
<dt>
<table class="standard-table">
<caption>
<h4 id="描述符可同时具有的键值">描述符可同时具有的键值</h4>
</caption>
<tbody>
<tr>
<td> </td>
<td>configurable</td>
<td>enumerable</td>
<td>value</td>
<td>writable</td>
<td>get</td>
<td>set</td>
</tr>
<tr>
<td>数据描述符</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td>存取描述符</td>
<td>Yes</td>
<td>Yes</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
<td>Yes</td>
</tr>
</tbody>
</table>
<p>如果一个描述符不具有value,writable,get 和 set 任意一个关键字，那么它将被认为是一个数据描述符。如果一个描述符同时有(value或writable)和(get或set)关键字，将会产生一个异常。</p>
</dt>
</dl>
<p>记住，这些选项不一定是自身属性，如果是继承来的也要考虑。为了确认保留这些默认值，你可能要在这之前冻结 <a href="Reference/Global_Objects/Object/prototype" title="Object.prototype 属性表示 Object 的原型对象。"><code>Object.prototype</code></a>，明确指定所有的选项，或者通过 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create" title="The Object.create() method creates a new object, using an existing object to provide the newly created object's __proto__ . (see browser console for visual evidence.)"><code>Object.create(null)</code></a>将<a class="new" href="Reference/Global_Objects/Object/__proto__" rel="nofollow" title="此页面仍未被本地化, 期待您的翻译!"><code>__proto__</code></a>属性指向<a href="Reference/Global_Objects/null" title="值 null 特指对象的值未设置。它是 JavaScript 基本类型 之一。"><code>null</code></a>。</p>
<pre><code  class="language-javascript">// 使用 __proto__
var obj = {};
var descriptor = Object.create(null); // 没有继承的属性
// 默认没有 enumerable，没有 configurable，没有 writable
descriptor.value = 'static';
Object.defineProperty(obj, 'key', descriptor);

// 显式
Object.defineProperty(obj, "key", {
  enumerable: false,
  configurable: false,
  writable: false,
  value: "static"
});

// 循环使用同一对象
function withValue(value) {
  var d = withValue.d || (
    withValue.d = {
      enumerable: false,
      writable: false,
      configurable: false,
      value: null
    }
  );
  d.value = value;
  return d;
}
// ... 并且 ...
Object.defineProperty(obj, "key", withValue("static"));

// 如果 freeze 可用, 防止代码添加或删除对象原型的属性
// （value, get, set, enumerable, writable, configurable）
(Object.freeze||Object)(Object.prototype);</code></pre>
<h2 id="Creating_a_property" name="Creating_a_property">示例</h2>
<p>如果你想了解如何使用<code>Object.defineProperty</code>方法和类二进制标记语法<span style="line-height: 1.5;">，看看</span><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty/Additional_examples" style="line-height: 1.5;" title="JavaScript/Reference/Global_Objects/Object/defineProperty/Additional_examples">这篇文章</a><span style="line-height: 1.5;">。</span></p>
<h3 id="Creating_a_property" name="Creating_a_property">创建属性</h3>
<p>如果对象中不存在指定的属性，<span style="font-family: courier new,andale mono,monospace; line-height: 1.5;"><code>Object.defineProperty()</code></span>就创建这个属性。当描述符中省略某些字段时，这些字段将使用它们的默认值。拥有布尔值的字段的默认值都是<span style="font-family: courier new,andale mono,monospace; line-height: 1.5;"><code>false</code></span>。<code>value</code>，<code>get</code>和<code>set</code>字段的默认值为<code>undefined</code>。一个没有<code>get/set/value/writable</code>定义的属性被称为“通用的”，并被“键入”为一个数据描述符。</p>
<pre><code  class="language-javascript">var o = {}; // 创建一个新对象

// 在对象中添加一个属性与数据描述符的示例
Object.defineProperty(o, "a", {
  value : 37,
  writable : true,
  enumerable : true,
  configurable : true
});

// 对象o拥有了属性a，值为37

// 在对象中添加一个属性与存取描述符的示例
var bValue;
Object.defineProperty(o, "b", {
  get : function(){
    return bValue;
  },
  set : function(newValue){
    bValue = newValue;
  },
  enumerable : true,
  configurable : true
});

o.b = 38;
// <span style="font-size: 1rem;">对象o拥有了属性b，值为38</span>

// o.b的值现在总是与bValue相同，除非重新定义o.b

// 数据描述符和存取描述符不能混合使用
Object.defineProperty(o, "conflict", {
  value: 0x9f91102, 
  get: function() { 
    return 0xdeadbeef; 
  } 
});
// throws a TypeError: value appears only in data descriptors, get appears only in accessor descriptors
</code></pre>
<h3 id="Modifying_a_property" name="Modifying_a_property">修改属性</h3>
<p>如果属性已经存在，<code>Object.defineProperty()</code>将尝试根据描述符中的值以及对象当前的配置来修改这个属性。如果旧描述符将其<code>configurable</code> 属性设置为<code>false</code>，则该属性被认为是“不可配置的”，并且没有属性可以被改变（除了单向改变 writable 为 false）。当属性不可配置时，不能在数据和访问器属性类型之间切换。</p>
<p>当试图改变不可配置属性（除了<code>value</code>和<code>writable</code> 属性之外）的值时会抛出<a href="Reference/Global_Objects/TypeError" title="TypeError（类型错误） 对象用来表示值的类型非预期类型时发生的错误。"><code>TypeError</code></a>，除非当前值和新值相同。</p>
<h4 id="Writable_attribute" name="Writable_attribute">Writable 属性</h4>
<p>当<code>writable</code>属性设置为<code>false</code>时，该属性被称为“不可写”。它不能被重新分配。</p>
<pre><code  class="language-javascript">var o = {}; // Creates a new object

Object.defineProperty(o, 'a', {
  value: 37,
  writable: false
});

console.log(o.a); // logs 37
o.a = 25; // No error thrown
// (it would throw in strict mode,
// even if the value had been the same)
console.log(o.a); // logs 37. The assignment didn't work.

// strict mode
(function() {
  'use strict';
  var o = {};
  Object.defineProperty(o, 'b', {
    value: 2,
    writable: false
  });
  o.b = 3; // throws TypeError: "b" is read-only
  return o.b; // returns 2 without the line above
}());</code></pre>
<p>如示例所示，试图写入非可写属性不会改变它，也不会引发错误。</p>
<h4 id="Enumerable_attribute" name="Enumerable_attribute">Enumerable 特性</h4>
<p> <code>enumerable</code>定义了对象的属性是否可以在 <a href="Reference/Statements/for...in" title="for...in语句以任意顺序遍历一个对象的可枚举属性。对于每个不同的属性，语句都会被执行。"><code>for...in</code></a> 循环和 <a href="Reference/Global_Objects/Object/keys" title="Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组，数组中属性名的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致 。"><code>Object.keys()</code></a> 中被枚举。</p>
<pre><code  class="language-javascript">var o = {};
Object.defineProperty(o, "a", { value : 1, enumerable:true });
Object.defineProperty(o, "b", { value : 2, enumerable:false });
Object.defineProperty(o, "c", { value : 3 }); // enumerable defaults to false
o.d = 4; // 如果使用直接赋值的方式创建对象的属性，则这个属性的enumerable为true

for (var i in o) {    
  console.log(i);  
}
// 打印 'a' 和 'd' (in undefined order)

Object.keys(o); // ["a", "d"]

o.propertyIsEnumerable('a'); // true
o.propertyIsEnumerable('b'); // false
o.propertyIsEnumerable('c'); // false
</code></pre>
<h4 id="Configurable_attribute" name="Configurable_attribute">Configurable 特性</h4>
<p><code>configurable</code>特性表示对象的属性是否可以被删除，以及除<code>value</code>和<code>writable</code>特性外的其他特性是否可以被修改。</p>
<pre><code  class="language-javascript">var o = {};
Object.defineProperty(o, "a", { get : function(){return 1;}, 
                                configurable : false } );

// throws a TypeError
Object.defineProperty(o, "a", {configurable : true}); 
// throws a TypeError
Object.defineProperty(o, "a", {enumerable : true}); 
// throws a TypeError (set was undefined previously) 
Object.defineProperty(o, "a", {set : function(){}}); 
// throws a TypeError (even though the new get does exactly the same thing) 
Object.defineProperty(o, "a", {get : function(){return 1;}});
// throws a TypeError
Object.defineProperty(o, "a", {value : 12});

console.log(o.a); // logs 1
delete o.a; // Nothing happens
console.log(o.a); // logs 1
</code></pre>
<p>如果<code>o.a</code>的<code>configurable</code>属性为<code>true</code>，则不会抛出任何错误，并且该属性将在最后被删除。</p>
<h3 id="Adding_properties_and_default_values" name="Adding_properties_and_default_values">添加多个属性和默认值</h3>
<p>考虑特性被赋予的默认特性值非常重要，通常，使用点运算符和<code>Object.defineProperty()</code>为对象的属性赋值时，数据描述符中的属性默认值是不同的，如下例所示。</p>
<pre><code  class="language-javascript">var o = {};

o.a = 1;
// 等同于 :
Object.defineProperty(o, "a", {
  value : 1,
  writable : true,
  configurable : true,
  enumerable : true
});


// 另一方面，
Object.defineProperty(o, "a", { value : 1 });
// 等同于 :
Object.defineProperty(o, "a", {
  value : 1,
  writable : false,
  configurable : false,
  enumerable : false
});
</code></pre>
<h3 id="一般的_Setters_和_Getters">一般的 Setters 和 Getters</h3>
<p>下面的例子展示了如何实现一个自存档对象。 当设置<code>temperature</code> 属性时，<code>archive</code> 数组会获取日志条目。</p>
<pre><code  class="language-javascript">function Archiver() {
  var temperature = null;
  var archive = [];

  Object.defineProperty(this, 'temperature', {
    get: function() {
      console.log('get!');
      return temperature;
    },
    set: function(value) {
      temperature = value;
      archive.push({ val: temperature });
    }
  });

  this.getArchive = function() { return archive; };
}

var arc = new Archiver();
arc.temperature; // 'get!'
arc.temperature = 11;
arc.temperature = 13;
arc.getArchive(); // [{ val: 11 }, { val: 13 }]</code></pre>
<p>或</p>
<pre><code  class="language-javascript">var pattern = {
    get: function () {
        return 'I alway return this string,whatever you have assigned';
    },
    set: function () {
        this.myname = 'this is my name string';
    }
};


function TestDefineSetAndGet() {
    Object.defineProperty(this, 'myproperty', pattern);
}


var instance = new TestDefineSetAndGet();
instance.myproperty = 'test';

// 'I alway return this string,whatever you have assigned'
console.log(instance.myproperty);
// 'this is my name string'
console.log(instance.myname);继承属性</code></pre>
<h3 id="继承属性">继承属性</h3>
<p>如果访问者的属性是被继承的，它的 <code>get</code> 和<code>set</code> 方法会在子对象的属性被访问或者修改时被调用。如果这些方法用一个变量存值，该值会被所有对象共享。</p>
<p> </p>
<pre><code  class="language-javascript">function myclass() {
}

var value;
Object.defineProperty(myclass.prototype, "x", {
  get() {
    return value;
  },
  set(x) {
    value = x;
  }
});

var a = new myclass();
var b = new myclass();
a.x = 1;
console.log(b.x); // 1</code></pre>
<p>这可以通过将值存储在另一个属性中解决。在 <code>get</code> 和 <code>set</code> 方法中，<code>this</code> 指向某个被访问和修改属性的对象。</p>
<p> </p>
<pre><code  class="language-javascript">function myclass() {
}

Object.defineProperty(myclass.prototype, "x", {
  get() {
    return this.stored_x;
  },
  set(x) {
    this.stored_x = x;
  }
});

var a = new myclass();
var b = new myclass();
a.x = 1;
console.log(b.x); // undefined</code></pre>
<p>不像访问者属性，值属性始终在对象自身上设置，而不是一个原型。然而，如果一个不可写的属性被继承，它仍然可以防止修改对象的属性。</p>
<p> </p>
<pre><code  class="language-javascript">function myclass() {
}

myclass.prototype.x = 1;
Object.defineProperty(myclass.prototype, "y", {
  writable: false,
  value: 1
});

var a = new myclass();
a.x = 2;
console.log(a.x); // 2
console.log(myclass.prototype.x); // 1
a.y = 2; // Ignored, throws in strict mode
console.log(a.y); // 1
console.log(myclass.prototype.y); // 1
</code></pre>
<h2 id="规范" style="margin-bottom: 20px; line-height: 30px;">规范</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">Specification</th>
<th scope="col">Status</th>
<th scope="col">Comment</th>
</tr>
<tr>
<td><a class="external" href="https://www.ecma-international.org/ecma-262/5.1/#sec-15.2.3.6" hreflang="en" lang="en" rel="noopener">ECMAScript 5.1 (ECMA-262)<br/><small lang="zh-CN">Object.defineProperty</small></a></td>
<td><span class="spec-Standard">Standard</span></td>
<td>Initial definition. Implemented in JavaScript 1.8.5.</td>
</tr>
<tr>
<td><a class="external" href="https://www.ecma-international.org/ecma-262/6.0/#sec-object.defineproperty" hreflang="en" lang="en" rel="noopener">ECMAScript 2015 (6th Edition, ECMA-262)<br/><small lang="zh-CN">Object.defineProperty</small></a></td>
<td><span class="spec-Standard">Standard</span></td>
<td> </td>
</tr>
<tr>
<td><a class="external" href="https://tc39.github.io/ecma262/#sec-object.defineproperty" hreflang="en" lang="en" rel="noopener">ECMAScript Latest Draft (ECMA-262)<br/><small lang="zh-CN">Object.defineProperty</small></a></td>
<td><span class="spec-Draft">Draft</span></td>
<td> </td>
</tr>
</tbody>
</table>
<h2 id="浏览器兼容">浏览器兼容</h2>
<div class="hidden">The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out <a class="external" href="https://github.com/mdn/browser-compat-data" rel="noopener">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</div>
<p></p><div class="bc-data"><a class="bc-github-link external" href="https://github.com/mdn/browser-compat-data" rel="noopener">Update compatibility data on GitHub</a><table class="bc-table bc-table-js"><thead><tr class="bc-platforms"><td></td><th class="bc-platform-desktop" colspan="6"><span>Desktop</span></th><th class="bc-platform-mobile" colspan="7"><span>Mobile</span></th><th class="bc-platform-server" colspan="1"><span>Server</span></th></tr><tr class="bc-browsers"><td></td><th class="bc-browser-chrome"><span class="bc-head-txt-label bc-head-icon-chrome">Chrome</span></th><th class="bc-browser-edge"><span class="bc-head-txt-label bc-head-icon-edge">Edge</span></th><th class="bc-browser-firefox"><span class="bc-head-txt-label bc-head-icon-firefox">Firefox</span></th><th class="bc-browser-ie"><span class="bc-head-txt-label bc-head-icon-ie">Internet Explorer</span></th><th class="bc-browser-opera"><span class="bc-head-txt-label bc-head-icon-opera">Opera</span></th><th class="bc-browser-safari"><span class="bc-head-txt-label bc-head-icon-safari">Safari</span></th><th class="bc-browser-webview_android"><span class="bc-head-txt-label bc-head-icon-webview_android">Android webview</span></th><th class="bc-browser-chrome_android"><span class="bc-head-txt-label bc-head-icon-chrome_android">Chrome for Android</span></th><th class="bc-browser-edge_mobile"><span class="bc-head-txt-label bc-head-icon-edge_mobile">Edge Mobile</span></th><th class="bc-browser-firefox_android"><span class="bc-head-txt-label bc-head-icon-firefox_android">Firefox for Android</span></th><th class="bc-browser-opera_android"><span class="bc-head-txt-label bc-head-icon-opera_android">Opera for Android</span></th><th class="bc-browser-safari_ios"><span class="bc-head-txt-label bc-head-icon-safari_ios">Safari on iOS</span></th><th class="bc-browser-samsunginternet_android"><span class="bc-head-txt-label bc-head-icon-samsunginternet_android">Samsung Internet</span></th><th class="bc-browser-nodejs"><span class="bc-head-txt-label bc-head-icon-nodejs">Node.js</span></th></tr></thead><tbody><tr><th scope="row"><code>defineProperty</code></th><td class="bc-supports-yes bc-browser-chrome"><span class="bc-browser-name">Chrome</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
              5</td><td class="bc-supports-yes bc-browser-edge"><span class="bc-browser-name">Edge</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
              12</td><td class="bc-supports-yes bc-browser-firefox"><span class="bc-browser-name">Firefox</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
              4</td><td class="bc-supports-yes bc-browser-ie bc-has-history"><span class="bc-browser-name">IE</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
              9<div class="bc-icons"><abbr class="only-icon" title="See implementation notes"><span>Notes</span><i class="ic-footnote"></i></abbr> </div><section class="bc-history" id="sect1"><dl><dt class="bc-supports-yes bc-supports"><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
              9<div class="bc-icons"><abbr class="only-icon" title="See implementation notes"><span>Notes</span><i class="ic-footnote"></i></abbr> </div></dt><dd><abbr class="only-icon" title="See implementation notes"><span>Notes</span><i class="ic-footnote"></i></abbr> Also supported in Internet Explorer 8, but only on DOM objects and with some non-standard behaviors.</dd></dl></section></td><td class="bc-supports-yes bc-browser-opera"><span class="bc-browser-name">Opera</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
              11.6</td><td class="bc-supports-yes bc-browser-safari bc-has-history"><span class="bc-browser-name">Safari</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
              5.1<div class="bc-icons"><abbr class="only-icon" title="See implementation notes"><span>Notes</span><i class="ic-footnote"></i></abbr> </div><section class="bc-history" id="sect2"><dl><dt class="bc-supports-yes bc-supports"><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
              5.1<div class="bc-icons"><abbr class="only-icon" title="See implementation notes"><span>Notes</span><i class="ic-footnote"></i></abbr> </div></dt><dd><abbr class="only-icon" title="See implementation notes"><span>Notes</span><i class="ic-footnote"></i></abbr> Also supported in Safari 5, but not on DOM objects.</dd></dl></section></td><td class="bc-supports-yes bc-browser-webview_android"><span class="bc-browser-name">WebView Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
              Yes</td><td class="bc-supports-yes bc-browser-chrome_android"><span class="bc-browser-name">Chrome Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
              Yes</td><td class="bc-supports-yes bc-browser-edge_mobile"><span class="bc-browser-name">Edge Mobile</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
              Yes</td><td class="bc-supports-yes bc-browser-firefox_android"><span class="bc-browser-name">Firefox Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
              4</td><td class="bc-supports-yes bc-browser-opera_android"><span class="bc-browser-name">Opera Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
              11.5</td><td class="bc-supports-yes bc-browser-safari_ios"><span class="bc-browser-name">Safari iOS</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
              Yes</td><td class="bc-supports-yes bc-browser-samsunginternet_android"><span class="bc-browser-name">Samsung Internet Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
              Yes</td><td class="bc-supports-yes bc-browser-nodejs"><span class="bc-browser-name">nodejs</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
              Yes</td></tr></tbody></table><section class="bc-legend" id="sect3"><h3 class="offscreen" id="Legend">Legend</h3><dl><dt><span class="bc-supports-yes bc-supports">
<abbr class="bc-level bc-level-yes only-icon" title="Full support">
<span>Full support</span>
                  
                </abbr></span></dt><dd>Full support</dd><dt><abbr class="only-icon" title="See implementation notes."><span>See implementation notes.</span><i class="ic-footnote"></i></abbr></dt><dd>See implementation notes.</dd></dl></section></div><p></p>
<h2 id="Cross-browser_concerns" name="Cross-browser_concerns">兼容性问题</h2>
<h3 id="Redefining_the_length_property_of_an_Array_object" name="Redefining_the_length_property_of_an_Array_object">重定义数组对象的 length 属性</h3>
<p>数组的 <a href="Reference/Global_Objects/Array/length" title="length 是Array的实例属性。返回或设置一个数组中的元素个数。该值是一个无符号 32-bit 整数，并且总是大于数组最高项的下标。"><code>length</code></a> 属性重定义是可能的，但是会受到一般的重定义限制。（<a href="Reference/Global_Objects/Array/length" title="length 是Array的实例属性。返回或设置一个数组中的元素个数。该值是一个无符号 32-bit 整数，并且总是大于数组最高项的下标。"><code>length</code></a> 属性初始为 non-configurable，non-enumerable 以及 writable。对于一个内容不变的数组，改变其 <a href="Reference/Global_Objects/Array/length" title="length 是Array的实例属性。返回或设置一个数组中的元素个数。该值是一个无符号 32-bit 整数，并且总是大于数组最高项的下标。"><code>length</code></a> 属性的值或者使它变为 non-writable 是可能的。但是改变其可枚举性和可配置性或者当它是 non-writable 时尝试改变它的值或是可写性，这两者都是不允许的。）然而，并不是所有的浏览器都允许 <code>Array.length</code> 的重定义。</p>
<p>在 Firefox 4 至 22 版本中尝试去重定义数组的 length 属性都会抛出一个 <a href="Reference/Global_Objects/TypeError" title="TypeError（类型错误） 对象用来表示值的类型非预期类型时发生的错误。"><code>TypeError</code></a> 异常。</p>
<p>有些版本的Chrome中，<code>Object.defineProperty()</code> 在某些情况下会忽略不同于数组当前<a href="Reference/Global_Objects/Array/length" title="length 是Array的实例属性。返回或设置一个数组中的元素个数。该值是一个无符号 32-bit 整数，并且总是大于数组最高项的下标。"><code>length</code></a>属性的length值。有些情况下改变可写性并不起作用（也不抛出异常）。同时，比如<a href="Reference/Global_Objects/Array/push" title="push() 方法将一个或多个元素添加到数组的末尾，并返回该数组的新长度。"><code>Array.prototype.push</code></a>的一些数组操作方法也不会考虑不可读的length属性。</p>
<p>有些版本的Safari中，<code>Object.defineProperty()</code>  在某些情况下会忽略不同于数组当前<a href="Reference/Global_Objects/Array/length" title="length 是Array的实例属性。返回或设置一个数组中的元素个数。该值是一个无符号 32-bit 整数，并且总是大于数组最高项的下标。"><code>length</code></a>属性的length值。尝试改变可写性的操作会正常执行而不抛出错误，但事实上并未改变属性的可写性。</p>
<p>只在Internet Explorer 9及以后版本和Firefox 23及以后版本中，才完整地正确地支持数组<a href="Reference/Global_Objects/Array/length" title="length 是Array的实例属性。返回或设置一个数组中的元素个数。该值是一个无符号 32-bit 整数，并且总是大于数组最高项的下标。"><code>length</code></a>属性的重新定义。目前不要依赖于重定义数组<a href="Reference/Global_Objects/Array/length" title="length 是Array的实例属性。返回或设置一个数组中的元素个数。该值是一个无符号 32-bit 整数，并且总是大于数组最高项的下标。"><code>length</code></a> 属性能够起作用，或在特定情形下起作用。与此同时，即使你能够依赖于它，你也<a class="external" href="http://whereswalden.com/2013/08/05/new-in-firefox-23-the-length-property-of-an-array-can-be-made-non-writable-but-you-shouldnt-do-it/" rel="noopener">没有合适的理由这样做</a>。</p>
<h3 id="Internet_Explorer_8_具体案例">Internet Explorer 8 具体案例</h3>
<p>Internet Explorer 8 实现了 <code>Object.defineProperty()</code> 方法，但 <a class="external" href="http://msdn.microsoft.com/en-us/library/dd229916%28VS.85%29.aspx" rel="noopener">只能在 DOM 对象上使用</a>。 需要注意的一些事情：</p>
<ul>
<li>尝试在原生对象上使用 <code>Object.defineProperty()会</code>报错。</li>
<li>属性特性必须设置一些特定的值。对于数据属性描述符，<code>configurable</code>, <code>enumerable </code>和 <code>writable </code>特性必须全部设置为 <code>true；</code>对于访问器属性描述符，<code>configurable </code>必须设置为 <code>true</code>，<code>enumerable </code>必须设置为 <code>false</code>。(?) 任何试图提供其他值(?)将导致一个错误抛出。</li>
<li>重新配置一个属性首先需要删除该属性。如果属性没有删除，就如同重新配置前的尝试。</li>
</ul>
<h2 id="See_also" name="See_also" style="margin-bottom: 20px; line-height: 30px;">相关链接</h2>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Enumerability_and_ownership_of_properties" title="Enumerability_and_ownership_of_properties">Enumerability and ownership of properties</a></li>
<li><a href="Reference/Global_Objects/Object/defineProperties" title="Object.defineProperties() 方法直接在一个对象上定义新的属性或修改现有属性，并返回该对象。"><code>Object.defineProperties()</code></a></li>
<li><a href="Reference/Global_Objects/Object/propertyIsEnumerable" title="propertyIsEnumerable() 方法返回一个布尔值，表示指定的属性是否可枚举。"><code>Object.propertyIsEnumerable()</code></a></li>
<li><a href="Reference/Global_Objects/Object/getOwnPropertyDescriptor" title="Object.getOwnPropertyDescriptor() 方法返回指定对象上一个自有属性对应的属性描述符。（自有属性指的是直接赋予该对象的属性，不需要从原型链上进行查找的属性）"><code>Object.getOwnPropertyDescriptor()</code></a></li>
<li><a href="Reference/Global_Objects/Object/watch" title="undefined."><code>Object.prototype.watch()</code></a></li>
<li><a href="Reference/Global_Objects/Object/unwatch" title="unwatch() 删除一个 watch() 设置的 watchpoint."><code>Object.prototype.unwatch()</code></a></li>
<li><a class="new" href="Reference/Operators/get" rel="nofollow" title="此页面仍未被本地化, 期待您的翻译!"><code>get</code></a></li>
<li><a class="new" href="Reference/Operators/set" rel="nofollow" title="此页面仍未被本地化, 期待您的翻译!"><code>set</code></a></li>
<li><a href="Reference/Global_Objects/Object/create" title="Object.create()方法创建一个新对象，使用现有的对象来提供新创建的对象的__proto__。 （请打开浏览器控制台以查看运行结果。）"><code>Object.create()</code></a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty/Additional_examples">Additional <code>Object.defineProperty</code> examples</a></li>
<li><a href="Reference/Global_Objects/Reflect/defineProperty" title="静态方法 Reflect.defineProperty() 基本等同于 Object.defineProperty() 方法，唯一不同是返回 Boolean 值。"><code>Reflect.defineProperty()</code></a></li>
</ul>
</article>